#ifndef _EVENT_HANDLER__H__
#define _EVENT_HANDLER__H__

#include "event.h"
#include "eventSupplier.h"
#include "eventConsumer.h"
#include "listeningObject.h"

//definiciones adelantadas
class EventHandlerSupplier; //implementacion de un event supplier
class EventHandlerConsumer; //implementacion de un event consumer
class EventHandler; //implementacion de un manejador de eventos distribuidos

/**
* @brief Clase encargada de manejar los eventos recibidos
* @author Carlos Rodriguez Dominguez
* 
* Subclase de EventConsumer que implementa los metodos virtuales
* "disconnect_push_consumer" y "push". Funcionara como event consumer
* propio para el manejador de eventos.
*/
class EventHandlerConsumer : public EventConsumer {
public:
	/**
	* Constructor
	*
	* @param c Comunicador ICE
	* @param host Host donde se encuentra el servicio de eventos
	* @param e Referencia al manejador de eventos
	*/
	EventHandlerConsumer(::Ice::CommunicatorPtr& c, const std::string& host, EventHandler* e);
	
	/**
	* Destructor
	*/
	~EventHandlerConsumer();
	
	/**
	* Se ejecutara al recibirse un evento. Se encarga de comprobar
	* si algun componente del manejador de eventos acepta el evento.
	* Si esto ocurre, entonces se ejecuta la accion asociada al listener
	* del evento recibido.
	*
	* @param data Evento recibido
	*/
	void push(const ::Collaboration::Event& evt,
                      const ::Ice::Current& c);
	
private:
	EventHandler* evh; /**< Manejador de eventos */
};

/**
* @brief Clase encargada de enviar eventos distribuidos (seran
*        recibidos por los event consumers en ejecucion)
* @author Carlos Rodriguez Dominguez
*
* Subclase de EventSupplier que implementa el metodo virtual
* "disconnect_push_supplier". Funcionara como event supplier
* propio para el manejador de eventos.
*/
class EventHandlerSupplier : public EventSupplier {
public:
	/**
	* Constructor
	*
	* @param c Comunicador ICE
	* @param host Host donde se encuentra el servicio de eventos
	* @param e Referencia al manejador de eventos
	*/
	EventHandlerSupplier(::Ice::CommunicatorPtr& c, const std::string& host, EventHandler* e);
	
	/**
	* Destructor
	*/
	~EventHandlerSupplier();
	
private:
	EventHandler* evh; /**< Manejador de eventos */
};

/**
* @brief Clase encargada de manejar eventos (envio y recepcion)
* @author Carlos Rodriguez Dominguez
* @date 13/11/2008
*
* Clase que permite registrar objetos, asi como enviar y recibir 
* eventos distribuidos. Para que se reciba un evento, debera haber
* registrado un objeto con un listener apropiado.
*/
class EventHandler {
public:
	/**
	* Constructor
	*
	* @param c Comunicador ICE
	* @param host Host donde se encuentra el servicio de eventos
	*/
	EventHandler(::Ice::CommunicatorPtr& c, const ::std::string& host);
	
	/**
	* Destructor
	*/
	~EventHandler();
	
	/**
	* Obtiene un vector con los objetos registrados
	* 
	* @return Vector con los objetos registrados
	*/
	::std::vector<ListeningObject*> getObjects();
	
	/**
	* Envia un evento
	* @param ev Evento a enviar
	*/
	void push(const Event& ev);
	
	/**
	* Registra un nuevo objeto que "escucha" eventos
	* distribuidos
	*
	* @param obj Objeto a registrar
	*/
	void registerObject(ListeningObject& obj);
	
	/**
	* Des-Registra un objeto que "escucha" eventos
	* distribuidos
	*
	* @param obj Objeto a des-registrar
	*/
	void unregisterObject(ListeningObject& obj);
	
	/**
	* Obtiene el comunicador de ICE asociado al manejador
	* de eventos.
	*/
	::Ice::CommunicatorPtr getCommunicator();
	
private:
	/**
	* Posicion de un objeto en el vector de objetos
	*
	* @param obj Objeto
	* @return Posicion del objeto o -1 si no existe
	*/
	int getPosObj(const ListeningObject& obj);
	
	::Ice::CommunicatorPtr comm;
	
	EventHandlerSupplier* channel_out; /**< Canal de salida para los eventos (event supplier) */
	EventHandlerConsumer* channel_input; /**< Canal de entrada para los eventos (event consumer) */
	
	::std::vector<ListeningObject*> objects; /**< Vector de objetos registrados */
};


#endif
